package com.ihrm.system.service;

import com.ihrm.common.entity.ResultCode;
import com.ihrm.common.exception.CommonException;
import com.ihrm.common.utils.BeanMapUtils;
import com.ihrm.common.utils.IdWorker;
import com.ihrm.common.utils.PermissionConstants;
import com.ihrm.domain.system.po.*;
import com.ihrm.domain.system.vo.PermissionResult;
import com.ihrm.system.dao.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class PermissionService {

    @Autowired
    private PermissionDao permissionDao;
    @Autowired
    private PermissionApiDao permissionApiDao;
    @Autowired
    private PermissionMenuDao permissionMenuDao;
    @Autowired
    private PermissionPointDao permissionPointDao;



    @Autowired
    private IdWorker idWorker;

    /**
     * 1.保存权限
     */
    public void save(Map<String, Object> map) throws Exception {
        String id = idWorker.nextId() + "";

        //1.通过map构造permission对象
        Permission perm = BeanMapUtils.mapToBean(map, Permission.class);
        perm.setId(id);
        permissionDao.save(perm);
        //2.根据类型构造不同的资源对象（菜单，按钮，api）
        int type = perm.getType();
        switch (type){
            case PermissionConstants.PERMISSION_MENU:
                PermissionMenu menu = BeanMapUtils.mapToBean(map, PermissionMenu.class);
                menu.setId(id);
                permissionMenuDao.save(menu);
                break;
            case PermissionConstants.PERMISSION_POINT:
                PermissionPoint point = BeanMapUtils.mapToBean(map, PermissionPoint.class);
                point.setId(id);
                permissionPointDao.save(point);
                break;
            case PermissionConstants.PERMISSION_API:
                PermissionApi api = BeanMapUtils.mapToBean(map, PermissionApi.class);
                api.setId(id);
                permissionApiDao.save(api);
                break;
            default:
                throw new CommonException(ResultCode.FAIL);
        }
    }

    /**
     * 2.更新用户
     */
    public void update(Map<String, Object> map) throws Exception {
        // 1. 根据type查询 用户信息 先查后改

        Permission perm = BeanMapUtils.mapToBean(map, Permission.class);
        permissionDao.save(perm);
        int type = perm.getType();
        String id = perm.getId();
        switch (type) {
            case PermissionConstants.PERMISSION_MENU:
                PermissionMenu tmpMenu =  permissionMenuDao.findById(id).get();
                PermissionMenu menu = BeanMapUtils.mapToBean(map, PermissionMenu.class);
                BeanUtils.copyProperties(menu,tmpMenu);
                permissionMenuDao.save(tmpMenu);
                break;
            case PermissionConstants.PERMISSION_POINT:
                PermissionPoint tmpPoint = permissionPointDao.findById(id).get();
                PermissionPoint point = BeanMapUtils.mapToBean(map, PermissionPoint.class);
                BeanUtils.copyProperties(point,tmpPoint);
                permissionPointDao.save(tmpPoint);
                break;
            case PermissionConstants.PERMISSION_API:
                PermissionApi tempApi = permissionApiDao.findById(id).get();
                PermissionApi api = BeanMapUtils.mapToBean(map, PermissionApi.class);
                BeanUtils.copyProperties(api,tempApi);
                permissionApiDao.save(tempApi);
                break;
            default:
                throw new CommonException(ResultCode.FAIL);
        }
    }


    /**
     * 3.根据id查询权限和权限对应的资源
     * 1.查询权限 //2.根据权限的类型查询资源 //3.构造vo对象
     */
    public PermissionResult findById(String id) throws CommonException {
        Permission perm = permissionDao.findById(id).get();
        int type = perm.getType();
        PermissionResult permissionResult = new PermissionResult();
        Object object = null;

        if (type == PermissionConstants.PERMISSION_MENU) {
            object = permissionMenuDao.findById(id).get();
            permissionResult.setPermissionMenu((PermissionMenu) object);
        }
        else if (type == PermissionConstants.PERMISSION_POINT) {
            object = permissionPointDao.findById(id).get();
            permissionResult.setPermissionPoint((PermissionPoint) object);
        }
        else if (type == PermissionConstants.PERMISSION_API) {
            object = permissionApiDao.findById(id).get();
            permissionResult.setPermissionApi((PermissionApi) object);
        }
        else {
            throw new CommonException(ResultCode.FAIL);
        }


        BeanUtils.copyProperties(perm,permissionResult);
        return permissionResult;
    }

    /**
     * 4.查询全部
     * <p>
     * 查询全部权限列表type：
     * <p>
     * 0：菜单 + 按钮（权限点）
     * <p>
     * 1：菜单
     * <p>
     * 2：按钮（权限点）
     * <p>
     * 3：API接口
     * <p>
     * enVisible :
     * <p>
     * 0：查询所有saas平台的最高权限，
     * <p>
     * 1：查询企业的权限
     * <p>
     * pid ：父id
     */
    public List<Permission> findAll(Map<String, Object> map) {
        //1.需要查询条件
        Specification<Permission> spec = new Specification<Permission>()
        {
            private static final long serialVersionUID = -9050875547500537750L;

            /**
             * 动态拼接查询条件
             * @return
             */
            @Override
            public Predicate toPredicate(Root<Permission> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<>();
                //根据父id查询
                if (!StringUtils.isEmpty(map.get("pid"))) {
                    list.add(criteriaBuilder.equal(root.get("pid").as(String.class), map.get("pid")));
                }
                //根据enVisible查询
                if (!StringUtils.isEmpty(map.get("enVisible"))) {
                    list.add(criteriaBuilder.equal(root.get("enVisible").as(String.class), map.get("enVisible")));
                }
                //根据类型 type
                if (!StringUtils.isEmpty(map.get("type"))) {
                    String ty = (String) map.get("type");
                    CriteriaBuilder.In<Object> in = criteriaBuilder.in(root.get("type"));
                    if ("0".equals(ty)) {
                        in.value(1).value(2);
                    }
                    else {
                        in.value(Integer.parseInt(ty));
                    }
                    list.add(in);
                }
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };
        return permissionDao.findAll(spec);
    }

    /**
     * 5.根据id删除 //1.删除权限 //2.删除权限对应的资源
     */
    public void deleteById(String id) throws Exception {
        //1.通过传递的权限id查询权限
        Permission permission = permissionDao.findById(id).get();
        permissionDao.delete(permission);
        //2.根据类型构造不同的资源
        int type = permission.getType();
        switch (type) {
            case PermissionConstants.PERMISSION_MENU:
                permissionMenuDao.deleteById(id);
                break;
            case PermissionConstants.PERMISSION_POINT:
                permissionPointDao.deleteById(id);
                break;
            case PermissionConstants.PERMISSION_API:
                permissionApiDao.deleteById(id);
                break;
            default:
                throw new CommonException(ResultCode.FAIL);
        }
    }

    public List<Permission> getMenuTree(String pid) {
        // 查询所有的节点
        List<Permission> all = permissionDao.findAll();

        // 构造根节点
        // List<Permission> permissionBase = permissionDao.selectByPid("0");
        List<Permission> permissionBase = all.stream().filter(permission -> permission.getPid().equals(pid)).collect(Collectors.toList());

        // 构造所有的非根节点
        List<Permission> permissionNotBase = all.stream().filter(permission -> !permission.getPid().equals("0")).collect(Collectors.toList());

        for (Permission p : permissionBase) {
            List<Permission> tmp = iterateMenus(permissionNotBase, p.getId());
            p.setChildren(tmp);
        }
        return permissionBase;
    }


    /**
     * 多级菜单查询方法
     *
     * @param menuVoList 不包含最高层次菜单的菜单集合
     * @param pid        父类id
     * @return
     */
    public List<Permission> iterateMenus(List<Permission> menuVoList, String pid) {
        List<Permission> result = new ArrayList<Permission>();
        for (Permission menu : menuVoList) {
            //获取菜单的id
            String menuid = menu.getId();
            //获取菜单的父id
            String parentid = menu.getPid();
            if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(parentid)) {
                if (parentid.equals(pid)) {
                    //递归查询当前子菜单的子菜单
                    List<Permission> iterateMenu = iterateMenus(menuVoList, menuid);
                    menu.setChildren(iterateMenu);
                    result.add(menu);
                }
            }
        }
        return result;
    }
}
